package xfuzzy.alg_genetico.indeterminado.model;

import xfuzzy.lang.*;
import xfuzzy.xfdm.model.*;
import xfuzzy.xfghl.algorithm.GeneticAlgorithm;
import xfuzzy.xfghl.model.XfghlConfig;
import xfuzzy.xfhl.model.XfhlConfig;
import xfuzzy.xfhl.model.XfhlProcess;
import xfuzzy.xfsl.model.*;
import xfuzzy.xfsim.model.*;
import xfuzzy.xfplot.model.*;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class MyXmlParser {

	// ----------------------------------------------------------------------------//
	// MIEMBROS PRIVADOS //
	// ----------------------------------------------------------------------------//

	/**
	 * Estructura de datos que almacena todo el documento XML
	 */
	private Document document;

	/**
	 * Lista de sistemas
	 */
	private Specification[] spec;

	/**
	 * Mensaje de error
	 */
	private String errormsg;

	// ----------------------------------------------------------------------------//
	// CONSTRUCTOR //
	// ----------------------------------------------------------------------------//

	/**
	 * Constructor
	 */
	public MyXmlParser() {
		this.spec = new Specification[0];
	}

	// ----------------------------------------------------------------------------//
	// METODOS PUBLICOS //
	// ----------------------------------------------------------------------------//

	/**
	 * Ejecuta el documento cargado
	 */
	public void execute() {
		
		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list.getLength() == 0)
			return;
		Node xfuzzy = list.item(0);

		NodeList xflist = xfuzzy.getChildNodes();
		for (int i = 0; i < xflist.getLength(); i++) {
			try {
				if (!execute(xflist.item(i))) {
					System.err.println(errormsg);
					break;
				}
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}

	/*
	 * Execute que no tiene en cuenta los comentarios y los textos public void
	 * execute() { NodeList list = this.document.getElementsByTagName("xfuzzy");
	 * if(list.getLength() == 0) return; Node xfuzzy = list.item(0);
	 * 
	 * NodeList xflist = xfuzzy.getChildNodes(); for(int i=0;
	 * i<xflist.getLength(); i++) {
	 * if(xflist.item(i).getNodeName().compareTo("#text")!=0 &&
	 * xflist.item(i).getNodeName().compareTo("#comment")!=0 &&
	 * !execute(xflist.item(i))) { System.err.println(errormsg); break; } } }
	 */

	/**
	 * A partir de un fichero XML se crea un documento DOM
	 * 
	 * @param file
	 * @return Document
	 */
	public boolean parseXML(File file) {
		
		try {
			DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			this.document = builder.parse(file);
			return true;
		} 
		catch (SAXParseException spe) {
			this.errormsg = "\n** Parsing error" + ", line " + spe.getLineNumber();
			this.errormsg += ", uri " + spe.getSystemId() + "\n";
			this.errormsg += "   " + spe.getMessage();
		} 
		catch (SAXException sxe) {
			this.errormsg = sxe.getMessage();
		} 
		catch (ParserConfigurationException pce) {
			this.errormsg = pce.getMessage();
		} 
		catch (IOException ioe) {
			this.errormsg = ioe.getMessage();
		} 
		catch (Exception e) {
			this.errormsg = e.getMessage();
		} 
		catch (Error e) {
			this.errormsg = e.getMessage();
		}
		return false;
	}

	/**
	 * Busca la configuraci�n de un proceso de aprendizaje en el fichero XML
	 * analizado
	 * 
	 * @return
	 */
	public XfslConfig getXfslConfig() {
		
		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list == null)
			return null;
		int length = list.getLength();
		if (length == 0)
			return null;

		for (int i = 0; i < length; i++) {
			Node xfuzzy = list.item(i);
			NodeList xflist = xfuzzy.getChildNodes();
			for (int j = 0; j < xflist.getLength(); j++) {
				String name = xflist.item(j).getNodeName();
				if (name.equals("xfsl"))
					return parseXfsl(xflist.item(j));
			}
		}
		return null;
	}

	/**
	 * Busca la configuracion de un proceso de simulacion en el fichero XML
	 * analizado
	 * 
	 * @return
	 */
	public XfsimConfig getXfsimConfig() {
		
		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list == null)
			return null;
		int length = list.getLength();
		if (length == 0)
			return null;

		for (int i = 0; i < length; i++) {
			Node xfuzzy = list.item(i);
			NodeList xflist = xfuzzy.getChildNodes();
			for (int j = 0; j < xflist.getLength(); j++) {
				String name = xflist.item(j).getNodeName();
				if (name.equals("xfsim"))
					return parseXfsim(xflist.item(j));
			}
		}
		return null;
	}

	/**
	 * Busca la configuracion de un proceso de representacion grafica en el
	 * fichero XML analizado
	 * 
	 * @return
	 */
	public XfplotConfig getXfplotConfig() {
		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list == null)
			return null;
		int length = list.getLength();
		if (length == 0)
			return null;

		for (int i = 0; i < length; i++) {
			Node xfuzzy = list.item(i);
			NodeList xflist = xfuzzy.getChildNodes();
			for (int j = 0; j < xflist.getLength(); j++) {
				String name = xflist.item(j).getNodeName();
				if (name.equals("xfplot"))
					return parseXfplot(xflist.item(j));
			}
		}
		return null;
	}

	/**
	 * Busca la configuracion de un proceso de extraccion de conocimiento en el
	 * fichero XML analizado
	 * 
	 * @return
	 */
	public XfdmConfig getXfdmConfig() {
		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list == null)
			return null;
		int length = list.getLength();
		if (length == 0)
			return null;

		for (int i = 0; i < length; i++) {
			Node xfuzzy = list.item(i);
			NodeList xflist = xfuzzy.getChildNodes();
			for (int j = 0; j < xflist.getLength(); j++) {
				String name = xflist.item(j).getNodeName();
				if (name.equals("xfdm"))
					return parseXfdm(xflist.item(j));
			}
		}
		return null;
	}

	/**
	 * Obtiene el mensaje de error
	 * 
	 * @return
	 */
	public String getErrorMessage() {
		return this.errormsg;
	}

	// ----------------------------------------------------------------------------//
	// METODOS PRIVADOS //
	// ----------------------------------------------------------------------------//

	// ----------------------------------------------------------------------------//
	// Metodos auxiliares //
	// ----------------------------------------------------------------------------//

	/**
	 * Busca por su nombre un sistema en la lista
	 */
	private Specification searchSystem(String name) {
		for (int i = 0, size = this.spec.length; i < size; i++) {
			if (spec[i].equals(name))
				return spec[i];
		}
		return null;
	}

	/**
	 * Añade un sistema difuso
	 * 
	 * @param ns
	 */
	private void addSystem(Specification ns) {
		Specification[] aux = new Specification[spec.length + 1];
		System.arraycopy(spec, 0, aux, 0, spec.length);
		aux[spec.length] = ns;
		this.spec = aux;
	}

	// ----------------------------------------------------------------------------//
	// Acciones del fichero XML //
	// ----------------------------------------------------------------------------//

	/**
	 * Ejecuta una accion del fichero XML
	 * 
	 * @param node
	 */
	private boolean execute(Node node) {
		String name = node.getNodeName();
		if (name.equals("createSystem"))
			return executeCreateSystem(node);
		if (name.equals("loadSystem"))
			return executeLoadSystem(node);
		if (name.equals("saveSystem"))
			return executeSaveSystem(node);
		if (name.equals("saveSystemAs"))
			return executeSaveSystemAs(node);
		// if(name.equals("xfedit")) return executeXfedit(node);
		if (name.equals("xfdm"))
			return executeXfdm(node);
		if (name.equals("xfsl"))
			return executeXfsl(node);
		// if(name.equals("xfsp")) return executeXfsp(node);
		// if(name.equals("xfmt")) return executeXfmt(node);
		// if(name.equals("xfplot")) return executeXfplot(node);
		if (name.equals("xfsim"))
			return executeXfsim(node);
		// if(name.equals("xfsw")) return executeXfsw(node);
		// if(name.equals("xfhw")) return executeXfhw(node);
		// this.errormsg = "Unknown tag "+name;

		if (name.equals("xfhl"))
			return executeXfhl(node);
		
		if (name.equals("xfghl"))
			return executeXfghl(node);

		// return true;

		this.errormsg = "Unknown tag " + name;

		return false;
	}

	/**
	 * Ejecuta una accion de creacion de un nuevo sistema
	 * 
	 * @param node
	 */
	private boolean executeCreateSystem(Node node) {
		NamedNodeMap map = node.getAttributes();
		Node namenode = map.getNamedItem("name");
		String name = namenode.getNodeValue();

		addSystem(new Specification(name));
		return true;
	}

	/**
	 * Ejecuta una accion de carga de un sistema
	 * 
	 * @param node
	 */
	private boolean executeLoadSystem(Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String path = fileNode.getNodeValue();

		XflParser parser = new XflParser();
		Specification system = parser.parse(path);
		if (system == null) {
			this.errormsg = parser.resume();
			return false;
		} else {
			addSystem(system);
			return true;
		}
	}

	/**
	 * Ejecuta una acci�n de guardar un sistema
	 * 
	 * @param node
	 * @return
	 */
	private boolean executeSaveSystem(Node node) {
		
		NamedNodeMap map = node.getAttributes();
		Node systemNode = map.getNamedItem("system");
		String systemName = systemNode.getNodeValue();
		Specification system = searchSystem(systemName);
		if (system == null) {
			this.errormsg = "Cannot find system " + systemName;
			return false;
		}
		if (!system.save()) {
			this.errormsg = "Cannot save system " + systemName;
			return false;
		}
		return true;
	}

	/**
	 * Ejecuta una acci�n de guardar un sistema en un fichero dado
	 * 
	 * @param node
	 * @return
	 */
	private boolean executeSaveSystemAs(Node node) {
		NamedNodeMap map = node.getAttributes();
		Node systemNode = map.getNamedItem("system");
		String systemName = systemNode.getNodeValue();
		Specification system = searchSystem(systemName);
		if (system == null) {
			this.errormsg = "Cannot find system " + systemName;
			return false;
		}
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();

		if (!system.save_as(new File(filePath))) {
			this.errormsg = "Cannot save system " + systemName;
			return false;
		}
		return true;
	}

	// ----------------------------------------------------------------------------//
	// Configuracion de la herramienta "xfhl" //
	// ----------------------------------------------------------------------------//

	private boolean executeXfhl(Node node) {

		XfhlConfig config = parseXfhl(node);
		if (config != null) {
			// Creamos el proceso
			XfhlProcess pro = new XfhlProcess(config);
			// Ejecutamos la herramienta
			pro.runBackground();
			// Añadimos el sistema de salida
			addSystem(pro.getBestData().getSpec());
			return true;
		} 
		else
			return false;
	}

	public XfhlConfig getXfhlConfig() {

		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list == null)
			return null;
		int length = list.getLength();
		if (length == 0)
			return null;

		for (int i = 0; i < length; i++) {
			Node xfuzzy = list.item(i);
			NodeList xflist = xfuzzy.getChildNodes();
			for (int j = 0; j < xflist.getLength(); j++) {
				String name = xflist.item(j).getNodeName();
				if (name.equals("xfhl"))
					return parseXfhl(xflist.item(j));
			}
		}
		return null;
	}
	
	// ----------------------------------------------------------------------------//
	// Configuracion de la herramienta "xfghl" //
	// ----------------------------------------------------------------------------//
	
	private boolean executeXfghl(Node node) {

		XfghlConfig config = parseXfghl(node);
		if (config != null) {
			// Creamos el proceso
			GeneticAlgorithm ga = new GeneticAlgorithm();
			ga.configure(config);
			Thread thread = new Thread(ga);
			// Ejecutamos la herramienta
			thread.start();
			try {
				thread.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			// Añadimos el sistema de salida
			addSystem(ga.getBest().getSpecification());
			
			
			
			return true;
		} 
		else
			return false;
	}
	
	public XfghlConfig getXfghlConfig()  {
		
		NodeList list = this.document.getElementsByTagName("xfuzzy");
		if (list == null)
			return null;
		int length = list.getLength();
		if (length == 0)
			return null;
		
		Node xfuzzy = null;
		NodeList xflist = null;
		for (int i = 0; i < length; i++)  {
			 xfuzzy = list.item(i);
			 xflist = xfuzzy.getChildNodes();
			 for (int j = 0; j < xflist.getLength(); j++)  {
				  String name = xflist.item(j).getNodeName();
				  if (name.equals("xfghl"))
					  return parseXfghl(xflist.item(j));
			 }
		}
		return null;
	}
	
	private XfghlConfig parseXfghl(Node node)  {
		
		Node systemNode = node.getAttributes().getNamedItem("system");
		String systemName = "";
		
		if (systemNode != null)
			systemName = systemNode.getNodeValue();
		else
			return null;
		
		XfghlConfig conf = null;
		try  {
			NodeList map = node.getChildNodes();
			// Variables de configuracion
			String name = "";
			String data = "";
			int numThread = -1;
			int numFun = -1;
			int inStyle = -1;
			int alg = -1;
			double iniUpd = -1;
			double incFact = -1;
			double decFact = -1;
			int numberIterations = -1;
			int operAnd = -1;
			int defuzOper = -1;
			File dataSetFile = null;
			double mutProb = -1, scaleFact = -1;
			int popSize = -1, tournamentSize = -1, stopSelec = -1, valueStop = -1;
			long mutationSeed = 0, crossSeed = 0, selectionSeed = 0, populationSeed = 0, replacementSeed = 0;
			String outputLog = "", outputBest = "";
			
			Node nodoEstudiado = null;
			for (int i = 0; i < map.getLength(); i++)  {
				 nodoEstudiado = map.item(i);
				 name = nodoEstudiado.getNodeName();
				 
				 if (name.compareTo("learning") == 0)  {
					 NamedNodeMap inType = nodoEstudiado.getAttributes();
					 alg = Integer.parseInt(inType.getNamedItem("algorithm").getNodeValue());
				 }
				// Data set file
				if (name.compareTo("dataset") == 0) {
					NamedNodeMap dataset = nodoEstudiado.getAttributes();
					data = dataset.getNamedItem("file").getNodeValue();
					dataSetFile = new File(data);
				}
				// Numero de threads
				else if (name.compareTo("threads") == 0) {
					NamedNodeMap numThreads = nodoEstudiado.getAttributes();
					String strNumbers = numThreads.getNamedItem("numbers").getNodeValue();
					if (strNumbers.compareTo("default") == 0) {
						numThread = -1;
					} else {
						numThread = Integer.parseInt(numThreads.getNamedItem("numbers").getNodeValue());
					}
				}
				// Tipo de entrada
				else if (name.compareTo("input_type") == 0) {
					NamedNodeMap inType = nodoEstudiado.getAttributes();
					inStyle = Integer.parseInt(inType.getNamedItem("style").getNodeValue());
					numFun = Integer.parseInt(inType.getNamedItem("num_funct").getNodeValue());
				}
				// Algoritmo RPROP Parametros
				else if (name.compareTo("alg_param") == 0) {
					NamedNodeMap rprop = nodoEstudiado.getAttributes();
					iniUpd = Double.parseDouble(rprop.getNamedItem("ini").getNodeValue());
					incFact = Double.parseDouble(rprop.getNamedItem("inc_fact").getNodeValue());
					decFact = Double.parseDouble(rprop.getNamedItem("dec_fact").getNodeValue());
				}
				// Numero de iteraciones
				else if (name.compareTo("end_condition") == 0) {
					NamedNodeMap endCond = nodoEstudiado.getAttributes();
					numberIterations = Integer.parseInt(endCond.getNamedItem("interations").getNodeValue());
				} 
				else if (name.compareTo("operartor_set") == 0) {
					// Conjunto de operadores
					NamedNodeMap operSet = nodoEstudiado.getAttributes();
					operAnd = Integer.parseInt(operSet.getNamedItem("and").getNodeValue());
					defuzOper = Integer.parseInt(operSet.getNamedItem("defuz").getNodeValue());
				}
				else if (name.compareTo("mutation") == 0)  {
					// Probabilidad de mutacion
					NamedNodeMap mutationNode = nodoEstudiado.getAttributes();
					mutProb = Double.parseDouble(mutationNode.getNamedItem("probability").getNodeValue());
					mutationSeed = Long.parseLong(mutationNode.getNamedItem("seed").getNodeValue());
				}
				else if (name.compareTo("crossover") == 0)  {
					// Semilla para el cruce
					NamedNodeMap crossNode = nodoEstudiado.getAttributes();
					crossSeed = Long.parseLong(crossNode.getNamedItem("seed").getNodeValue());
				}
				else if (name.compareTo("population") == 0)  {
					// Individuos de la poblacion
					NamedNodeMap populationNode = nodoEstudiado.getAttributes();
					popSize = Integer.parseInt(populationNode.getNamedItem("size").getNodeValue());
					populationSeed = Long.parseLong(populationNode.getNamedItem("seed").getNodeValue());
				}
				else if (name.compareTo("selection") == 0)  {
					NamedNodeMap selectionNode = nodoEstudiado.getAttributes();
					tournamentSize = Integer.parseInt(selectionNode.getNamedItem("tournamente_size").getNodeValue());
					selectionSeed = Long.parseLong(selectionNode.getNamedItem("seed").getNodeValue());
				}
				else if (name.compareTo("replacement") == 0)  {
					// Factor de escala en el reemplazo
					NamedNodeMap scalingFactorNode = nodoEstudiado.getAttributes();
					scaleFact = Double.parseDouble(scalingFactorNode.getNamedItem("scaling_factor").getNodeValue());
					replacementSeed = Long.parseLong(scalingFactorNode.getNamedItem("seed").getNodeValue());
				}
				else if (name.compareTo("stopGA") == 0)  {
					NamedNodeMap stopNode = nodoEstudiado.getAttributes();
					stopSelec = Integer.parseInt(stopNode.getNamedItem("condition").getNodeValue());
					valueStop = Integer.parseInt(stopNode.getNamedItem("value").getNodeValue());
				}
				else if (name.compareTo("output") == 0)  {
					NamedNodeMap outputNode = nodoEstudiado.getAttributes();
					outputBest = outputNode.getNamedItem("best").getNodeValue();
					outputLog = outputNode.getNamedItem("log").getNodeValue();
				}
			}
			// Creamos la configuracion sino ha habido ningun error
			conf = new XfghlConfig(systemName, numberIterations, numThread, dataSetFile, iniUpd, incFact, decFact,
						operAnd, defuzOper, inStyle, numFun, alg, mutProb, popSize, tournamentSize, scaleFact, stopSelec, valueStop);
			conf.setCrossoverSeed(crossSeed);
			conf.setMutationSeed(mutationSeed);
			conf.setPopopulationSeed(populationSeed);
			conf.setReplacementSeed(replacementSeed);
			conf.setSelectionSeed(selectionSeed);
			conf.setOutputBest(outputBest);
			conf.setLogFile(outputLog);
		} 
		catch (Exception e) {
			this.errormsg = "Error in the configuration XFGHL";
			conf = null;
		}
		return conf;
	}

	private XfhlConfig parseXfhl(Node node) {
		
		Node systemNode = node.getAttributes().getNamedItem("system");
		String systemName = "";

		if (systemNode != null)
			systemName = systemNode.getNodeValue();
		else
			return null;

		XfhlConfig conf = null;

		try {
			NodeList map = node.getChildNodes();
			// Variables de la configuracion
			String data = "";
			int numThread = -1;
			int numFun = -1;
			int inStyle = -1;
			int alg = -1;
			double iniUpd = -1;
			double incFact = -1;
			double decFact = -1;
			int numberIterations = -1;
			int operAnd = -1;
			int defuzOper = -1;
			File dataSetFile = null;

			for (int i = 0; i < map.getLength(); i++) {
				Node nodoEstudiado = map.item(i);
				String name = nodoEstudiado.getNodeName();

				// Algoritmo de aprendizaje
				if (name.compareTo("learning") == 0) {
					NamedNodeMap inType = nodoEstudiado.getAttributes();
					alg = Integer.parseInt(inType.getNamedItem("algorithm").getNodeValue());
				}
				// Data set file
				if (name.compareTo("dataset") == 0) {
					NamedNodeMap dataset = nodoEstudiado.getAttributes();
					data = dataset.getNamedItem("file").getNodeValue();
					dataSetFile = new File(data);
				}
				// Numero de threads
				else if (name.compareTo("threads") == 0) {
					NamedNodeMap numThreads = nodoEstudiado.getAttributes();
					String strNumbers = numThreads.getNamedItem("numbers").getNodeValue();
					if (strNumbers.compareTo("default") == 0) {
						numThread = -1;
					} else {
						numThread = Integer.parseInt(numThreads.getNamedItem("numbers").getNodeValue());
					}
				}
				// Tipo de entrada
				else if (name.compareTo("input_type") == 0) {
					NamedNodeMap inType = nodoEstudiado.getAttributes();
					inStyle = Integer.parseInt(inType.getNamedItem("style").getNodeValue());
					numFun = Integer.parseInt(inType.getNamedItem("num_funct").getNodeValue());
				}
				// Algoritmo RPROP Parametros
				else if (name.compareTo("alg_param") == 0) {
					NamedNodeMap rprop = nodoEstudiado.getAttributes();
					iniUpd = Double.parseDouble(rprop.getNamedItem("ini").getNodeValue());
					incFact = Double.parseDouble(rprop.getNamedItem("inc_fact").getNodeValue());
					decFact = Double.parseDouble(rprop.getNamedItem("dec_fact").getNodeValue());
				}
				// Numero de iteraciones
				else if (name.compareTo("end_condition") == 0) {
					NamedNodeMap endCond = nodoEstudiado.getAttributes();
					numberIterations = Integer.parseInt(endCond.getNamedItem("interations").getNodeValue());
				} else if (name.compareTo("operartor_set") == 0) {
					// Conjunto de operadores
					NamedNodeMap operSet = nodoEstudiado.getAttributes();
					operAnd = Integer.parseInt(operSet.getNamedItem("and").getNodeValue());
					defuzOper = Integer.parseInt(operSet.getNamedItem("defuz").getNodeValue());

				}
			}
			// Creamos la configuracion sino ha habido ningun error
			conf = new XfhlConfig(systemName, numberIterations, numThread, dataSetFile, iniUpd, incFact, decFact,
					operAnd, defuzOper, inStyle, numFun, alg);

		} catch (Exception e) {
			this.errormsg = "Error in the configuration XFHL";
			conf = null;
		}
		return conf;
	}

	// ----------------------------------------------------------------------------//
	// Configuracion de la herramienta "xfsl" //
	// ----------------------------------------------------------------------------//

	/**
	 * Ejecuta un proceso de ajuste param�trico
	 * 
	 * @param node
	 * @return
	 */
	private boolean executeXfsl(Node node) {
		NamedNodeMap map = node.getAttributes();
		Node systemNode = map.getNamedItem("system");
		String systemName = systemNode.getNodeValue();
		Specification system = searchSystem(systemName);
		if (system == null) {
			this.errormsg = "Cannot find system " + systemName;
			return false;
		}

		XfslConfig config = parseXfsl(node);
		if (config == null)
			return false;

		XfslThread xfsl = new XfslThread(system, config);
		try {
			xfsl.learning();
		} catch (XflException ex) {
			this.errormsg = ex.toString();
			return false;
		}
		if (config.outputfile != null)
			system.save_as(config.outputfile);
		else
			system.save();

		return true;
	}

	/**
	 * Obtiene la configuraci�n de un proceso de ajuste param�trico a partir de
	 * una definici�n XML
	 * 
	 * @param node
	 * @return
	 */
	private XfslConfig parseXfsl(Node node) {
		XfslConfig config = new XfslConfig();
		NodeList nodeList = node.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node xfslnode = nodeList.item(i);
			if (!parseXfslNode(config, xfslnode))
				return null;
		}
		return config;
	}

	/**
	 * Analiza cada nodo de la etiqueta "xfsl"
	 * 
	 * @param config
	 * @param node
	 */
	private boolean parseXfslNode(XfslConfig config, Node node) {
		String nodeName = node.getNodeName();

		if (nodeName.equals("training"))
			return parseXfslTrainingNode(config, node);
		if (nodeName.equals("test"))
			return parseXfslTestNode(config, node);
		if (nodeName.equals("log"))
			return parseXfslLogNode(config, node);
		if (nodeName.equals("output"))
			return parseXfslOutputNode(config, node);
		if (nodeName.equals("algorithm"))
			return parseXfslAlgorithmNode(config, node);
		if (nodeName.equals("error_function"))
			return parseXfslErrorFunctionNode(config, node);
		if (nodeName.equals("end_condition"))
			return parseXfslEndConditionNode(config, node);
		if (nodeName.equals("enable"))
			return parseXfslEnableNode(config, node);
		if (nodeName.equals("disable"))
			return parseXfslDisableNode(config, node);

		// this.errormsg = "Unknown tag '"+nodeName+"'";
		return true;
	}

	/**
	 * Analiza una etiqueta "training" dentro de una configuraci�n "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslTrainingNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		if (!file.exists()) {
			this.errormsg = "Cannot find file " + filePath;
			return false;
		}
		config.trainingfile = file;
		return true;
	}

	/**
	 * Analiza una etiqueta "test" dentro de una configuraci�n "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslTestNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		if (!file.exists()) {
			this.errormsg = "Cannot find file " + filePath;
			return false;
		}
		config.testfile = file;
		return true;
	}

	/**
	 * Analiza una etiqueta "log" dentro de una configuraci�n "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslLogNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);

		Vector<String> vector = new Vector<String>();

		NodeList vars = node.getChildNodes();

		for (int i = 0, length = vars.getLength(); i < length; i++) {
			Node var = vars.item(i);
			Node varname = var.getAttributes().getNamedItem("name");
			vector.add(varname.getNodeValue());
		}

		config.logfile = new XfslLog(file, vector);
		return true;
	}

	/**
	 * Analiza una etiqueta "output" dentro de una configuracion "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslOutputNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		config.outputfile = file;
		return true;
	}

	/**
	 * Analiza una etiqueta "algorithm" dentro de una configuracion "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslAlgorithmNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node algNode = map.getNamedItem("name");
		String algName = algNode.getNodeValue();

		NodeList paramNodes = node.getChildNodes();
		double[] param = new double[paramNodes.getLength()];
		int size = 0;
		for (int i = 0, length = paramNodes.getLength(); i < length; i++) {
			Node paramNode = paramNodes.item(i);
			NamedNodeMap nmap = paramNode.getAttributes();
			if (nmap == null)
				continue;
			Node paramValue = nmap.getNamedItem("value");
			if (paramValue == null)
				continue;
			param[size] = Double.parseDouble(paramValue.getNodeValue());
			size++;
		}
		double[] p = new double[size];
		System.arraycopy(param, 0, p, 0, size);

		try {
			config.algorithm = XfslAlgorithmFactory.createAlgorithm(algName, p);
		} catch (Exception ex) {
			return false;
		}
		return true;
	}

	/**
	 * Analiza una etiqueta "error_function" dentro de una configuracion "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslErrorFunctionNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node errorNode = map.getNamedItem("name");
		String errorName = errorNode.getNodeValue();

		NodeList paramNodes = node.getChildNodes();
		double[] param = new double[paramNodes.getLength()];
		int size = 0;
		for (int i = 0, length = paramNodes.getLength(); i < length; i++) {
			Node paramNode = paramNodes.item(i);
			NamedNodeMap nmap = paramNode.getAttributes();
			if (nmap == null)
				continue;
			Node paramValue = nmap.getNamedItem("value");
			if (paramValue == null)
				continue;
			param[size] = Double.parseDouble(paramValue.getNodeValue());
			size++;
		}
		double[] p = new double[size];
		System.arraycopy(param, 0, p, 0, size);

		try {
			if (p.length == 0)
				config.errorfunction = new XfslErrorFunction(errorName);
			else
				config.errorfunction = new XfslErrorFunction(errorName, p);
		} catch (Exception ex) {
			return false;
		}
		return true;
	}

	/**
	 * Analiza una etiqueta "end_condition" dentro de una configuraci�n "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslEndConditionNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node condNameNode = map.getNamedItem("name");
		String condName = condNameNode.getNodeValue();
		Node condValueNode = map.getNamedItem("value");
		String condValue = condValueNode.getNodeValue();
		double value = Double.parseDouble(condValue);
		config.endcondition.set(condName, value);
		return true;
	}

	/**
	 * Analiza una etiqueta "enable" dentro de una configuraci�n "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslEnableNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node settingNode = map.getNamedItem("value");
		String setting = settingNode.getNodeValue();
		config.addSetting(setting, true);
		return true;
	}

	/**
	 * Analiza una etiqueta "disable" dentro de una configuraci�n "xfsl"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfslDisableNode(XfslConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node settingNode = map.getNamedItem("value");
		String setting = settingNode.getNodeValue();
		config.addSetting(setting, false);
		return true;
	}

	// ----------------------------------------------------------------------------//
	// Configuraci�n de la herramienta "xfsim" //
	// ----------------------------------------------------------------------------//

	/**
	 * Ejecuta un proceso de simulaci�n
	 * 
	 * @param node
	 * @return
	 */
	private boolean executeXfsim(Node node) {
		NamedNodeMap map = node.getAttributes();
		Node systemNode = map.getNamedItem("system");
		if (systemNode == null) {
			this.errormsg = "Cannot find system ";
			return false;
		}

		String systemName = systemNode.getNodeValue();
		Specification system = searchSystem(systemName);
		if (system == null) {
			this.errormsg = "Cannot find system " + systemName;
			return false;
		}

		XfsimConfig config = parseXfsim(node);
		if (config == null)
			return false;

		XfsimThread xfsim = new XfsimThread(system, config);
		xfsim.run();
		return true;
	}

	/**
	 * Obtiene la configuraci�n de un proceso de simulaci�n a partir de una
	 * definici�n XML
	 * 
	 * @param node
	 * @return
	 */
	private XfsimConfig parseXfsim(Node node) {
		XfsimConfig config = new XfsimConfig();
		NodeList nodeList = node.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node xfsimnode = nodeList.item(i);
			if (!parseXfsimNode(config, xfsimnode))
				return null;
		}
		return config;
	}

	/**
	 * Analiza cada nodo de la etiqueta "xfsim"
	 * 
	 * @param config
	 * @param node
	 */
	private boolean parseXfsimNode(XfsimConfig config, Node node) {
		String nodeName = node.getNodeName();

		if (nodeName.equals("plant"))
			return parseXfsimPlantNode(config, node);
		if (nodeName.equals("init"))
			return parseXfsimInitNode(config, node);
		if (nodeName.equals("limits"))
			return parseXfsimLimitNode(config, node);
		if (nodeName.equals("log"))
			return parseXfsimLogNode(config, node);
		if (nodeName.equals("plot"))
			return parseXfsimPlotNode(config, node);

		// this.errormsg = "Unknown tag '"+nodeName+"'";
		return true;
	}

	/**
	 * Analiza un nodo "plant" de la etiqueta "xfsim"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfsimPlantNode(XfsimConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		try {
			config.setPlantModel(file);
			return true;
		} catch (XflException ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "init" de la etiqueta "xfsim"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfsimInitNode(XfsimConfig config, Node node) {
		try {
			NodeList nodeList = node.getChildNodes();
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node initnode = nodeList.item(i);
				if (initnode.getNodeName().equals("var")) {
					NamedNodeMap map = initnode.getAttributes();
					Node nameNode = map.getNamedItem("name");
					String name = nameNode.getNodeValue();
					Node valueNode = map.getNamedItem("value");
					String value = valueNode.getNodeValue();
					config.setPlantInit(name, value);
				}
			}
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "limits" de la etiqueta "xfsim"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfsimLimitNode(XfsimConfig config, Node node) {
		try {
			NodeList nodeList = node.getChildNodes();
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node initnode = nodeList.item(i);
				if (initnode.getNodeName().equals("n_limit")) {
					NamedNodeMap map = initnode.getAttributes();
					Node valueNode = map.getNamedItem("value");
					int value = Integer.parseInt(valueNode.getNodeValue());
					config.getLimit().setNLimit(value);
				} else if (initnode.getNodeName().equals("t_limit")) {
					NamedNodeMap map = initnode.getAttributes();
					Node valueNode = map.getNamedItem("value");
					double value = Double.parseDouble(valueNode.getNodeValue());
					config.getLimit().setTLimit(value);
				} else if (initnode.getNodeName().equals("i_low_limit")) {
					NamedNodeMap map = initnode.getAttributes();
					Node indexNode = map.getNamedItem("index");
					int index = Integer.parseInt(indexNode.getNodeValue());
					Node valueNode = map.getNamedItem("value");
					double value = Double.parseDouble(valueNode.getNodeValue());
					config.getLimit().setInputLowLimit(index, value);
				} else if (initnode.getNodeName().equals("i_high_limit")) {
					NamedNodeMap map = initnode.getAttributes();
					Node indexNode = map.getNamedItem("index");
					int index = Integer.parseInt(indexNode.getNodeValue());
					Node valueNode = map.getNamedItem("value");
					double value = Double.parseDouble(valueNode.getNodeValue());
					config.getLimit().setInputHighLimit(index, value);
				} else if (initnode.getNodeName().equals("o_low_limit")) {
					NamedNodeMap map = initnode.getAttributes();
					Node indexNode = map.getNamedItem("index");
					int index = Integer.parseInt(indexNode.getNodeValue());
					Node valueNode = map.getNamedItem("value");
					double value = Double.parseDouble(valueNode.getNodeValue());
					config.getLimit().setOutputLowLimit(index, value);
				} else if (initnode.getNodeName().equals("o_high_limit")) {
					NamedNodeMap map = initnode.getAttributes();
					Node indexNode = map.getNamedItem("index");
					int index = Integer.parseInt(indexNode.getNodeValue());
					Node valueNode = map.getNamedItem("value");
					double value = Double.parseDouble(valueNode.getNodeValue());
					config.getLimit().setOutputHighLimit(index, value);
				}
			}
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "log" de la etiqueta "xfsim"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfsimLogNode(XfsimConfig config, Node node) {
		try {
			NamedNodeMap map = node.getAttributes();
			Node fileNode = map.getNamedItem("file");
			String filePath = fileNode.getNodeValue();
			File file = new File(filePath);
			XfsimLog log = new XfsimLog(0, 0);
			log.setFile(file);
			NodeList nodeList = node.getChildNodes();
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node writenode = nodeList.item(i);
				if (writenode.getNodeName().equals("write")) {
					NamedNodeMap attr = writenode.getAttributes();
					Node varNode = attr.getNamedItem("var");
					String var = varNode.getNodeValue();
					if (var.equals("n"))
						log.setNSelection(true);
					else if (var.equals("t"))
						log.setTSelection(true);
					else if (var.startsWith("i")) {
						int index = Integer.parseInt(var.substring(1));
						log.setInputSelection(index, true);
					} else if (var.startsWith("o")) {
						int index = Integer.parseInt(var.substring(1));
						log.setOutputSelection(index, true);
					}
				}
			}
			config.addOutput(log);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "plot" de la etiqueta "xfsim"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfsimPlotNode(XfsimConfig config, Node node) {
		try {
			NamedNodeMap map = node.getAttributes();
			Node xvarNode = map.getNamedItem("xvar");
			String xvar = xvarNode.getNodeValue();
			Node yvarNode = map.getNamedItem("yvar");
			String yvar = yvarNode.getNodeValue();
			Node kindNode = map.getNamedItem("kind");
			int kind = Integer.parseInt(kindNode.getNodeValue());
			config.addOutput(new XfsimPlot(xvar, yvar, kind));
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	// ----------------------------------------------------------------------------//
	// Configuracion de la herramienta "xfplot" //
	// ----------------------------------------------------------------------------//

	/**
	 * Obtiene la configuraci�n de un proceso de simulaci�n a partir de una
	 * definici�n XML
	 * 
	 * @param node
	 * @return
	 */
	private XfplotConfig parseXfplot(Node node) {
		XfplotConfig config = new XfplotConfig();
		NodeList nodeList = node.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node xfsimnode = nodeList.item(i);
			if (!parseXfplotNode(config, xfsimnode))
				return null;
		}
		return config;
	}

	/**
	 * Analiza cada nodo de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 */
	private boolean parseXfplotNode(XfplotConfig config, Node node) {
		String nodeName = node.getNodeName();

		if (nodeName.equals("graph3D"))
			return parseXfplotGraph3DNode(config, node);
		if (nodeName.equals("graph2D"))
			return parseXfplotGraph2DNode(config, node);
		if (nodeName.equals("input"))
			return parseXfplotInputNode(config, node);
		if (nodeName.equals("perspective"))
			return parseXfplotPerspectiveNode(config, node);
		if (nodeName.equals("samples"))
			return parseXfplotSamplesNode(config, node);
		if (nodeName.equals("colormode"))
			return parseXfplotColormodeNode(config, node);

		// this.errormsg = "Unknown tag '"+nodeName+"'";
		return true;
	}

	/**
	 * Analiza un nodo "graph3D" de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfplotGraph3DNode(XfplotConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node xNode = map.getNamedItem("xvar");
		Node yNode = map.getNamedItem("yvar");
		Node zNode = map.getNamedItem("zvar");
		try {
			int xi = Integer.parseInt(xNode.getNodeValue().substring(1));
			int yi = Integer.parseInt(yNode.getNodeValue().substring(1));
			int zi = Integer.parseInt(zNode.getNodeValue().substring(1));
			config.setVariables(xi, yi, zi);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "graph2D" de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfplotGraph2DNode(XfplotConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node xNode = map.getNamedItem("xvar");
		Node yNode = map.getNamedItem("yvar");
		try {
			int xi = Integer.parseInt(xNode.getNodeValue().substring(1));
			int yi = Integer.parseInt(yNode.getNodeValue().substring(1));
			config.setVariables(xi, yi);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "perspective" de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfplotPerspectiveNode(XfplotConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node hslideNode = map.getNamedItem("hslide");
		Node vslideNode = map.getNamedItem("vslide");
		try {
			int hslide = Integer.parseInt(hslideNode.getNodeValue());
			int vslide = Integer.parseInt(vslideNode.getNodeValue());
			config.setSlides(hslide, vslide);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "colormode" de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfplotSamplesNode(XfplotConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node valueNode = map.getNamedItem("value");
		try {
			int samples = Integer.parseInt(valueNode.getNodeValue());
			config.setSamples(samples);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "colormode" de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfplotColormodeNode(XfplotConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node valueNode = map.getNamedItem("value");
		try {
			int colormode = Integer.parseInt(valueNode.getNodeValue());
			config.setColorMode(colormode);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un node "input" de la etiqueta "xfplot"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfplotInputNode(XfplotConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node nameNode = map.getNamedItem("name");
		Node valueNode = map.getNamedItem("value");
		try {
			int index = Integer.parseInt(nameNode.getNodeValue().substring(1));
			double value = Double.parseDouble(valueNode.getNodeValue());
			config.setInputValue(index, value);
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	// ----------------------------------------------------------------------------//
	// Configuraci�n de la herramienta "xfdm" //
	// ----------------------------------------------------------------------------//

	/**
	 * Ejecuta un proceso de extracci�n de conocimiento
	 * 
	 * @param node
	 * @return
	 */
	private boolean executeXfdm(Node node) {
		NamedNodeMap map = node.getAttributes();
		Node systemNode = map.getNamedItem("system");
		String systemName = systemNode.getNodeValue();
		Specification system = searchSystem(systemName);
		if (system == null) {
			this.errormsg = "Cannot find system " + systemName;
			return false;
		}

		XfdmConfig config = parseXfdm(node);
		if (config == null)
			return false;
		config.setSpecification(system);

		XfdmThread xfdm = new XfdmThread(config);

		try {
			xfdm.exec();
		} catch (Exception ex) {
			this.errormsg = ex.toString();
			return false;
		}

		return true;
	}

	/**
	 * Obtiene la configuraci�n de un proceso de extracci�n de conocimiento a
	 * partir de una definici�n XML
	 * 
	 * @param node
	 * @return
	 */
	private XfdmConfig parseXfdm(Node node) {
		XfdmConfig config = new XfdmConfig();
		NodeList nodeList = node.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node xfdmnode = nodeList.item(i);
			if (!parseXfdmNode(config, xfdmnode))
				return null;
		}
		return config;
	}

	/**
	 * Analiza cada nodo de la etiqueta "xfdm"
	 * 
	 * @param config
	 * @param node
	 */
	private boolean parseXfdmNode(XfdmConfig config, Node node) {
		String nodeName = node.getNodeName();

		if (nodeName.equals("dataset"))
			return parseXfdmDataSetNode(config, node);
		if (nodeName.equals("datatest"))
			return parseXfdmDataTestNode(config, node);
		if (nodeName.equals("log"))
			return parseXfdmLogNode(config, node);
		if (nodeName.equals("algorithm"))
			return parseXfdmAlgorithmNode(config, node);
		if (nodeName.equals("input"))
			return parseXfdmInputNode(config, node);
		if (nodeName.equals("system"))
			return parseXfdmSystemNode(config, node);

		// this.errormsg = "Unknown tag '"+nodeName+"'";
		return true;
	}

	/**
	 * Analiza una etiqueta "dataset" dentro de una configuraci�n "xfdm"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfdmDataSetNode(XfdmConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		return config.setDataSet(file);
	}

	/**
	 * Analiza una etiqueta "datatest" dentro de una configuraci�n "xfdm"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfdmDataTestNode(XfdmConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		return config.setDataTest(file);
	}

	/**
	 * Analiza una etiqueta "log" dentro de una configuraci�n "xfdm"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfdmLogNode(XfdmConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node fileNode = map.getNamedItem("file");
		String filePath = fileNode.getNodeValue();
		File file = new File(filePath);
		config.setLogFile(file);
		return true;
	}

	/**
	 * Analiza una etiqueta "algorithm" dentro de una configuraci�n "xfdm"
	 * 
	 * @param config
	 * @param node
	 * @return
	 */
	private boolean parseXfdmAlgorithmNode(XfdmConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node algNode = map.getNamedItem("name");
		String algName = algNode.getNodeValue();

		NodeList paramNodes = node.getChildNodes();
		double[] param = new double[paramNodes.getLength()];
		int size = 0;
		for (int i = 0, length = paramNodes.getLength(); i < length; i++) {
			Node paramNode = paramNodes.item(i);
			if (!paramNode.getNodeName().equals("param"))
				continue;
			NamedNodeMap nmap = paramNode.getAttributes();
			if (nmap == null)
				continue;
			Node paramValue = nmap.getNamedItem("value");
			if (paramValue == null)
				continue;
			param[size] = Double.parseDouble(paramValue.getNodeValue());
			size++;
		}
		double[] p = new double[size];
		System.arraycopy(param, 0, p, 0, size);

		try {
			config.setAlgorithm(XfdmAlgorithmFactory.create(algName, p));
		} catch (Exception ex) {
			return false;
		}
		return true;
	}

	/**
	 * Analiza un nodo "input" de la etiqueta "xfdm"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfdmInputNode(XfdmConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node indexNode = map.getNamedItem("index");
		Node mfsNode = map.getNamedItem("mfs");
		Node styleNode = map.getNamedItem("style");
		try {
			int index = Integer.parseInt(indexNode.getNodeValue());
			int mfs = Integer.parseInt(mfsNode.getNodeValue());
			int style = Integer.parseInt(styleNode.getNodeValue());
			config.addInputStyle(new XfdmInputStyle(index, mfs, style));
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}

	/**
	 * Analiza un nodo "system" de la etiqueta "xfdm"
	 * 
	 * @param config
	 * @param node
	 * @return true si no se encuentran errores
	 */
	private boolean parseXfdmSystemNode(XfdmConfig config, Node node) {
		NamedNodeMap map = node.getAttributes();
		Node baseNode = map.getNamedItem("base");
		Node andNode = map.getNamedItem("and");
		Node defuzNode = map.getNamedItem("defuz");
		Node creationNode = map.getNamedItem("creation");
		try {
			String base = baseNode.getNodeValue();
			int and = Integer.parseInt(andNode.getNodeValue());
			int defuz = Integer.parseInt(defuzNode.getNodeValue());
			boolean creation = Boolean.parseBoolean(creationNode.getNodeValue());
			config.setSystemStyle(new XfdmSystemStyle(base, and, defuz, creation));
			return true;
		} catch (Exception ex) {
			this.errormsg += ex.getMessage();
			return false;
		}
	}
}
